#pragma once
#include"Common.hpp"
#include"Channel.hpp"
#include"Poller.hpp"
#include "TimerWheel.hpp"

class EventLoop
{
private:
    using Task_t = std::function<void()>;
    using Functor = std::function<void()>;
    std::thread::id _thread_id; // 线程ID
    int _event_fd;              // eventfd唤醒IO事件监控有可能导致的阻塞
    std::unique_ptr<Channel> _event_channel;
    Poller _poller;              // 进⾏所有描述符的事件监控
    std::vector<Functor> _tasks; // 任务池
    std::mutex _mutex;           // 实现任务池操作的线程安全
    TimerWheel _timer_wheel;     // 定时器模块
public:
    // 执⾏任务池中的所有任务
    void RunAllTask()
    {
        LOG(DEBUG, "开始执行任务池中的任务,数量：%d\n", _tasks.size());
        std::vector<Functor> functor;
        {
            std::unique_lock<std::mutex> _lock(_mutex);
            _tasks.swap(functor);
        }
        // 交换任务直接执行，避免长时间阻塞!
        for (auto &task : functor)
        {
            task();
        }
        return;
    }
    static int CreateEventFd()
    {
        LOG(DEBUG, "创建eventfd完毕!\n");
        int efd = ::eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
        if (efd < 0)
        {
            LOG(ERROR, "EventLoop中创建eventfd异常!\n");
            abort(); // 让程序异常退出
        }
        LOG(DEBUG, "创建eventfd完毕,fd = %d\n", efd);
        return efd;
    }
    void ReadEventfd()
    {
        LOG(DEBUG, "向eventfd写入数据完毕!\n");
        uint64_t res = 0;
        int ret = read(_event_fd, &res, sizeof(res));
        if (ret < 0)
        {
            // EINTR -- 被信号打断； EAGAIN -- 表⽰⽆数据可读
            if (errno == EINTR || errno == EAGAIN)
            {
                return;
            }
            LOG(ERROR, "EventLoop向eventfd读取数据异常!\n");
            abort();
        }
        return;
    }
    void WeakUpEventFd()
    {
        LOG(DEBUG, "对eventfd读取数据完毕!\n");
        uint64_t val = 1;
        int ret = write(_event_fd, &val, sizeof(val));
        if (ret < 0)
        {
            if (errno == EINTR)
            {
                return;
            }
            LOG(ERROR, "EventLoop向eventfd写入数据异常!\n");
            abort();
        }
        return;
    }

public:
    EventLoop() : _thread_id(std::this_thread::get_id()),
                  _event_fd(CreateEventFd()),
                  _event_channel(new Channel(this, _event_fd)),
                  _timer_wheel(this)
    {
        // 给eventfd添加可读事件回调函数，读取eventfd事件通知次数
        LOG(DEBUG, "eventLoop---关联的线程id = %u\n", _thread_id);
        _event_channel->SetReadCallback(std::bind(&EventLoop::ReadEventfd, this));
        // 启动eventfd的读事件监控
        _event_channel->OpenReadEventMonitoring();
    }
    void Start()
    {
        while (true)
        {
            // 1. 事件监控，
            std::vector<Channel *> actives;
            _poller.Poll(&actives);
            // 2. 事件处理。
            for (auto &channel : actives)
            {
                channel->HandleEvent();
            }
            // 3. 执⾏任务
            RunAllTask();
        }
    }
    // ⽤于判断当前线程是否是EventLoop对应的线程；
    bool IsInLoop()
    {
        return (_thread_id == std::this_thread::get_id());
    }
    void AssertInLoop()
    {
        assert(_thread_id == std::this_thread::get_id());
    }
    // 判断将要执⾏的任务是否处于当前线程中，如果是则执⾏，不是则压⼊队列。
    void RunInLoop(const Functor &cb)
    {
        if (IsInLoop())
        {
            return cb();
        }
        return QueueInLoop(cb);
    }
    // 将操作压⼊任务池
    void QueueInLoop(const Functor &cb)
    {
        {
            std::unique_lock<std::mutex> _lock(_mutex);
            _tasks.push_back(cb);
        }
        // 唤醒有可能因为没有事件就绪，⽽导致的epoll阻塞；
        // 其实就是给eventfd写⼊⼀个数据，eventfd就会触发可读事件
        WeakUpEventFd();
    }
    // 添加/修改描述符的事件监控
    void UpdateEvent(Channel *channel)
    {
        return _poller.UpdateEvent(channel);
    }
    // 移除描述符的监控
    void RemoveEvent(Channel *channel)
    {
        return _poller.RemoveEvent(channel);
    }
    void TimerAdd(uint64_t id, uint32_t timeout, const Task_t &cb)
    {
        return _timer_wheel.AddTaskToTimerWheelInLoop(cb, timeout, id);
    }
    void TimerRefresh(uint64_t id)
    {
        return _timer_wheel.RefreshTaskInLoop(id);
    }
    void TimerCancel(uint64_t id)
    {
        return _timer_wheel.CancelTaskInLoop(id);
    }
    bool HasTimer(uint64_t id)
    {
        return _timer_wheel.HasTask(id);
    }
};
void Channel::Remove()
{
    _loop->RemoveEvent(this);
}
void Channel::Update()
{
    _loop->UpdateEvent(this);
}

// 在一个loop循环中处理添加任务
void TimerWheel::AddTaskToTimerWheelInLoop(const Run_cb &run_cb, int timeout, uint64_t id)
{
    _loop->RunInLoop(std::bind(&TimerWheel::TimerTaskAdd, this, run_cb, timeout, id));
}
// 刷新/延迟定时任务
void TimerWheel::RefreshTaskInLoop(uint64_t id)
{
    return _loop->RunInLoop(std::bind(&TimerWheel::RefreshTimeTask, this, id));
}
void TimerWheel::CancelTaskInLoop(uint64_t id)
{
    return _loop->RunInLoop(std::bind(&TimerWheel::CancelTask, this, id));
}